package com.weilele.mvvm.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.weilele.mvvm.utils.activity.onClick
import com.weilele.mvvm.utils.safeGet
import java.lang.IllegalArgumentException
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

class DefaultMvvmAdapterImpl<Data> : IMvvmAdapter<Data> {

    private val holders = mutableListOf<HolderBean>()

    private var mViewType = 0

    private data class HolderBean(
        val holderCls: Class<*>,
        val beanType: Type?,
        val type: Int = -1,
        val block: Function2<LayoutInflater, ViewGroup, MvvmHolder<*, *>>? = null
    )


    /**
     * 设置点击事件
     */
    private val itemClickMap =
        hashMapOf<Int?, ((holder: MvvmHolder<Data, *>, clickView: View) -> Unit)?>()

    /**
     * 长按事件
     */
    private val itemLongClickMap =
        hashMapOf<Int?, ((holder: MvvmHolder<Data, *>, clickView: View) -> Unit)?>()

    /**
     *滚动到最后，用于分页
     */
    private var onScrollEndListener: Function1<Int, Unit>? = null

    /**
     * 如果只注册了一个holder，直接是用这个，提升性能
     */
    private var defaultHolder: HolderBean? = null

    override fun onMvvmCreateViewHolder(parent: ViewGroup, viewType: Int): MvvmHolder<Data, *> {
        var bean = defaultHolder
        var holderCls: Class<MvvmHolder<Data, *>>? = bean?.holderCls.safeGet()
        if (holderCls == null) {
            holders.forEach {
                if (it.type == viewType) {
                    holderCls = it.holderCls.safeGet()
                    bean = it
                    return@forEach
                }
            }
        }
        val inflater = LayoutInflater.from(parent.context)
        val holder = bean?.block?.invoke(inflater, parent)?.safeGet<MvvmHolder<Data, *>>()
        if (holder != null) {
            return setClickEvent(holder, parent)
        }
        if (holderCls == null) {
            throw IllegalArgumentException("不能找到[viewType ${viewType}],对应的MvvmHolder，请检查是否注册对应的MvvmHolder")
        }
        return setClickEvent(
            holderCls!!.createHolderInstance(
                inflater,
                parent,
                false
            ), parent
        )
    }

    override fun onMvvmBindViewHolder(
        holder: MvvmHolder<Data, *>,
        position: Int,
        payloads: MutableList<Any>,
        isScrollEnd: Boolean,
        item: Data?
    ) {
        if (onScrollEndListener != null && isScrollEnd) {
            onScrollEndListener?.invoke(position)
        }
        if (item != null) {
            holder.onBindData(position, item, payloads)
        }
    }


    override fun getMvvmItemViewType(position: Int, item: Data?): Int {
        val defaultViewType = defaultHolder?.type
        if (defaultViewType != null) {
            return defaultViewType
        }
        item ?: return 0
        var viewType: Int? = null
        val beanCls = item!!::class.java
        holders.forEach {
            if (it.beanType == beanCls) {
                viewType = it.type
                return it.type
            }
        }
        if (viewType == null) {
            throw IllegalArgumentException(
                "不能找到数据[\n位置：${position}\n类型：${beanCls}\n值：${item}\n]" +
                        ",对应的viewType，请检查是否注册对应的MvvmHolder"
            )
        }
        return viewType!!
    }

    override fun onMvvmViewAttachedToWindow(holder: MvvmHolder<Data, *>) {
        holder.onViewAttachedToWindow()
    }

    override fun onMvvmViewDetachedFromWindow(holder: MvvmHolder<Data, *>) {
        holder.onViewDetachedFromWindow()
    }

    override fun onMvvmViewRecycled(holder: MvvmHolder<Data, *>) {
        holder.onViewRecycled()
    }

    override fun onMvvmFailedToRecycleView(holder: MvvmHolder<Data, *>) {
        holder.onFailedToRecycleView()
    }

    override fun <DataType : Data, Holder : MvvmHolder<DataType, *>> register(holderCls: Class<Holder>) {
        var had = false
        holders.forEach Holder@{ bean ->
            if (bean.holderCls == holderCls) {
                had = true
                return@Holder
            }
        }
        if (!had) {
            holders.add(
                HolderBean(
                    holderCls,
                    getRealType(holderCls.getParameterizedType()?.actualTypeArguments?.get(0)),
                    ++mViewType
                )
            )
        }
        initDefaultHolder()
    }

    override fun <DataType : Data> register(
        dataCls: Class<DataType>,
        block: (LayoutInflater, ViewGroup) -> MvvmHolder<DataType, *>
    ) {
        holders.add(HolderBean(MvvmHolder::class.java, dataCls, ++mViewType, block))
        initDefaultHolder()
    }


    override fun <DataType : Data, Holder : MvvmHolder<DataType, *>> unRegister(holderCls: Class<Holder>) {
        holders.toMutableList().forEach { bean ->
            if (bean.holderCls == holderCls) {
                holders.remove(bean)
            }
        }
        initDefaultHolder()
    }

    private fun initDefaultHolder() {
        defaultHolder = if (holders.count() == 1) {
            holders[0]
        } else {
            null
        }
    }

    private fun getRealType(old: Type?): Type {
        if (old == null) {
            throw IllegalArgumentException("holderClass 只能是[MvvmHolder]类型")
        }
        return if (old is ParameterizedType) {
            old.rawType
        } else {
            old
        }
    }

    /**
     * 是否设置点击事件
     * 防止创建过多无用的对象
     */
    private fun setClickEvent(holder: MvvmHolder<Data, *>, parent: ViewGroup): MvvmHolder<Data, *> {
        holder.parent = parent
        for ((itemClickId, listener) in itemClickMap) {
            val view: View? = if (itemClickId != null) {
                holder.itemView.findViewById(itemClickId)
            } else {
                holder.itemView
            }
            view?.onClick {
                listener?.invoke(holder, it)
            }
        }
        for ((itemClickId, listener) in itemLongClickMap) {
            val view: View? = if (itemClickId != null) {
                holder.itemView.findViewById(itemClickId)
            } else {
                holder.itemView
            }
            view?.setOnLongClickListener {
                listener?.invoke(holder, it)
                true
            }
        }
        return holder
    }

    override fun setOnHolderClickListener(
        clickId: Int?,
        listener: ((holder: MvvmHolder<Data, *>, clickView: View) -> Unit)
    ) {
        itemClickMap[clickId] = listener
    }

    override fun setOnHolderLongClickListener(
        clickId: Int?,
        listener: ((holder: MvvmHolder<Data, *>, clickView: View) -> Unit)
    ) {
        itemLongClickMap[clickId] = listener
    }

    /**
     * 设置滑到底部的监听
     */
    override fun setOnScrollEndListener(l: Function1<Int, Unit>?) {
        this.onScrollEndListener = l
    }

    override fun getItemData(position: Int): Data? {
        throw IllegalArgumentException("请重写此函数,实现自己逻辑")
    }

}